#!/usr/bin/env python
#coding=utf-8

import time
import sys, getopt
import traceback
from multiprocessing import Process
import signal
import port_check

from scapy.all import *

# ------- MENU -------
def usage():
    print "\nscan-ap 1.0 by xtr4nge"
    
    print "Usage: scan-ap.py <options>\n"
    print "Options:"
    print "-i <i>, --interface=<i>                  set interface (default: mon0)"
    print "-t <type>, --type=<type>                 type filter (default: 0)"
    print "-s <subtype> --subtype=<subtype>         subtypes filters (default: 0,1,2,3,4,5,8)"
    print "-d <delay>, --delay=<delay>              write delay (default: 2s)"
    print "-l <log>, --log=<log>                    log file path"
    print "-c <channel>, --channel=<channel>        channel hopping (default: 1,2,3,4,5,...13)"
    print "-h                                       Print this help message."
    print ""
    print "Author: xtr4nge"
    print ""

def parseOptions(argv):
    INTERFACE = "wlp2s0" # server, minion
    TYPE =  "0,1"
    LOG = ""
    SUBTYPE = "0,1,2,3,4,5,8,10,11,12,13"
    DELAY = 2
    #CHANNEL = "1,2,3,4,5,6,7,8,9,10,11,12,13"
    CHANNEL="11"

    try:
        opts, args = getopt.getopt(argv, "hi:t:l:s:d:c:",
                                   ["help", "interface=", "type=", "log=", "subtype=", "delay=", "channel="])

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                usage()
                sys.exit()
            elif opt in ("-i", "--interface"):
                INTERFACE = arg
            elif opt in ("-t", "--type"):
                TYPE = arg
            elif opt in ("-l", "--log"):
                LOG = arg
                with open(LOG, 'w') as f:
                    f.write("")
            elif opt in ("-s", "--subtype"):
                SUBTYPE = arg
            elif opt in ("-d", "--delay"):
                DELAY = int(arg)
            elif opt in ("-c", "--channel"):
                CHANNEL = arg
        
        # TYPE INTO INT ARRAY
        TEMP = CHANNEL.split(",")
        CHANNEL = []
        for i in TEMP:
            CHANNEL.append(int(i))
        
        # TYPE INTO INT ARRAY
        TEMP = TYPE.split(",")
        TYPE = []
        for i in TEMP:
            TYPE.append(int(i))

        # SUBTYPE INTO INT ARRAY
        TEMP = SUBTYPE.split(",")
        SUBTYPE = []
        for i in TEMP:
            SUBTYPE.append(int(i))

        return (INTERFACE, TYPE, LOG, SUBTYPE, DELAY, CHANNEL)
                    
    except getopt.GetoptError:           
        usage()
        sys.exit(2) 

# -------------------------
# GLOBAL VARIABLES
# -------------------------
desc = {
        0: "Association Request", 
        1: "Association Response",
        2: "Reassociation Request",
        3: "Reassociation Response",
        4: "Probe Request",
        5: "Probe Response",
        8: "Beacon Frame",
        9: "ATIM",
        10: "Disassociation",
        11: "Authentication",
        12: "Deauthentication",
        13: "Acknowledgement",
    }

white_list={}
INVENTORY = {}
EXCLUDE = [None, "00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff"]
aps = {}
(INTERFACE, TYPE, LOG, SUBTYPE, DELAY, CHANNEL) = parseOptions(sys.argv[1:])

CHANNEL_SCAN=6
init_delay_time = int(time.time())
MACWhiteList=["06:5f:a7:76:75:d8","44:c8:74:ee:2f:7a"]
SSIDWhiteList=["JCG-6675D8-2.4G"]

fakeap_list={}
#统计每种类型的帧数量
last_sc={}

init_sc_last_becon={}
fakeap_sc_time_list={}
fakeap_signal_time_list={}
#DOS VARIABLE
#接受到指定类型包的所有设备，但不是只要接受到了该设备就被攻击
devdic={}
#Deauth攻击
deauthAttackdic={}
#Disassociation攻击
disassociationAttackdic={}
authAttackdic={}
#AuthAttack攻击
authAttackTimes=0

'''
SC域,SequenceControl包含了SequenceNumber和FragmentNumber字段，fragmentnumber占低四位
每一个beancon帧的sequencenumber都比上一个+1，又因为低在beancon帧中为0，所以换成十进制SC每次都+16
'''

'''
伪ap的ssid和mac,append方式追加
'''
def update_fakeaplist(SSID, currentMAC,mac_check,signal,sc,channel):
    reason = set()
    if mac_check==False:
        reason.add("mac not in whitelist")
    else:
        if signal == False:
            reason.add("signal error")
        if sc == False:
            reason.add("sequence number error")
        if channel==False:
            reason.add("channel error")

    fakeap_list[SSID] = [currentMAC, reason]
    # if (SSID in fakeap_list.keys()):
    #     if (currentMAC not in fakeap_list[SSID]):
    #         fakeap_list[SSID].append([currentMAC,reason])
    # else:
    #     fakeap_list[SSID] = [currentMAC,reason]
'''
True:设备MAC在白名单中或者SSID不属于白名单
'''
def check_ssid_bssid_in_whitelist(SSID, currentMAC):
    res=True
    if (SSID in SSIDWhiteList):
        if (currentMAC not in MACWhiteList):
            res=False
    return res
'''
只处理设备MAC在白名单中的包
'''
def compare_sc_diff(packet):
    res=True
    current_mac=packet.addr2
    ssid=packet.info
    if(current_mac not in last_sc.keys()):
        last_sc[current_mac]=packet.SC
        return True

    lastSC = last_sc[current_mac]
    #print(lastSC)
    currentSC = packet.SC
    #print(currentSC)
    #检查到序列号不对后，不再对该热点的序列号进行更新
    if (abs(currentSC - lastSC)/16 > aps[current_mac][6]):
        #print abs(currentSC - lastSC)/16
        last_sc[current_mac] = currentSC
        if ssid in fakeap_sc_time_list.keys():
            fakeap_sc_time_list[ssid]+=1
        else:
            fakeap_sc_time_list[ssid]=1
        res=False
    else:
        last_sc[current_mac]=currentSC
    return res

def compare_signal_diff(signal,ssid,bssid):
    if signal < aps[bssid][4] or signal > aps[bssid][5]:
        signal_check = False
        if ssid in fakeap_signal_time_list.keys():
            fakeap_signal_time_list[ssid]+=1
        else:
            fakeap_signal_time_list[ssid]=1
    return True
def print_message():
    for i in INVENTORY:

        o_bssid = str(i)
        try:
            o_ssid = str(aps[i][0])
        except:
            o_ssid = ""
        try:
            o_channel = str(aps[i][1])
        except:
            o_channel = ""
        try:
            o_crypto = str("|".join(aps[i][2]))
        except:
            o_crypto = ""
        try:
            o_signal = str(aps[i][3])
        except:
            o_signal = ""
        o_client = str("|".join(INVENTORY[i]))
        try:
            o_min_signal = str(aps[i][4])
        except:
            o_min_signal = ""
        try:
            o_max_signal = str(aps[i][5])
        except:
            o_max_signal = ""
        OUT = o_bssid + "," + o_ssid + "," + o_channel + "," + o_crypto + "," + o_signal + "," + o_min_signal + "," + o_max_signal + "," + o_client
        if o_ssid !="":
            print OUT

# -------------------------
# SNIFFER INIT
# -------------------------
def sniffmgmt_init(p):
    global TYPE
    global SUBTYPE
    global LOG
    global DELAY
    global init_delay_time
    global f
    IP = []
    
    try:
        
        SIGNAL = -(256-ord(p.notdecoded[-4:-3]))
        #p = pkt[Dot11Elt]
        cap = p.sprintf("{Dot11Beacon:%Dot11Beacon.cap%}"
                          "{Dot11ProbeResp:%Dot11ProbeResp.cap%}").split('+')
        
        BSSID = ""
        SSID, CHANNEL = None, None
        crypto = []
        pDot11Elt = None
        CLIENT = ""

        try: pDot11Elt= p[Dot11Elt]
        except: pass
        while isinstance(pDot11Elt, Dot11Elt):
            BSSID = p[Dot11].addr3

            if pDot11Elt.ID == 0:
                SSID = p.info
            elif pDot11Elt.ID == 3:
                CHANNEL = ord(pDot11Elt.info)
            elif pDot11Elt.ID == 48:
                crypto.append("WPA2")
            elif pDot11Elt.ID == 221 and pDot11Elt.info.startswith('\x00P\xf2\x01\x01\x00'):
                crypto.append("WPA")
            pDot11Elt = pDot11Elt.payload
        #新增加一个接入点
        if SSID != None and SSID != "" and BSSID not in aps and BSSID not in EXCLUDE:
            #print BSSID, SSID, CHANNEL, crypto, SIGNAL
            aps[BSSID] = [SSID, CHANNEL, crypto, SIGNAL,SIGNAL,SIGNAL,0]
        elif BSSID in aps:
            aps[BSSID][3] = SIGNAL
            if SIGNAL<aps[BSSID][4]:
                aps[BSSID][4]=SIGNAL
            if SIGNAL>aps[BSSID][5]:
                aps[BSSID][5]=SIGNAL
        
        IP.append(str(p.addr1))
        IP.append(str(p.addr2))
        IP.append(str(p.addr3))


        if p.subtype in SUBTYPE: # DEBUG
            pass
            #print p.type, p.subtype, IP, desc[p.subtype], SSID, CHANNEL, SIGNAL
        #return
        
        # TYPE = 0
        
        # BSSID, CLIENT, BSSID 
        if p.type == 0 and p.subtype == 0: # Association Request
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1
        
        # CLIENT, BSSID, BSSID 
        if p.type == 0 and p.subtype == 1: # Association Response
            #print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr2
        
        # CLIENT, FF: # + SSID (sometimes)
        if p.type == 0 and p.subtype == 4: # Probe Request
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            try: SSID = str(p.info)
            except: SSID = ""
        
        # CLIENT, BSSID, BSSID # + SSID
        if p.type == 0 and p.subtype == 5: # Probe Response
            #print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr3
            try: SSID = str(p.info)
            except: SSID = ""
        
        # 00:, BSSID, BSSID # + SSID
        if p.type == 0 and p.subtype == 8: # Beacon Frame
            #print p.addr2, p.addr3
            #CLIENT = p.addr2
            BSSID = p.addr2
            try:
                SSID = str(p.info)

                if BSSID in init_sc_last_becon.keys():
                    diff=abs(p.SC - init_sc_last_becon[BSSID])/16
                    #print diff
                    #print aps[BSSID][6]
                    init_sc_last_becon[BSSID]=p.SC
                    if diff < 500 and diff>aps[BSSID][6]:
                        aps[BSSID][6]=diff
                else:
                    init_sc_last_becon[BSSID]=p.SC
                    aps[BSSID][6]=0
            except: SSID = ""
        
        # BSSID, CLIENT, BSSID 
        if p.type == 0 and p.subtype == 10: # Disassociation
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1
        
        # CLIENT, BSSID, BSSID 
        if p.type == 0 and p.subtype == 11: # Authentication
            #print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr2
        
        # CLIENT, BSSID [re-check] (NOT IN BSSID?)
        if p.type == 0 and p.subtype == 13: # Acknowledgement | Action frames
            pass
            #print p.addr2, p.addr3
            #CLIENT = p.addr2
            #BSSID = p.addr1
        
        # TYPE = 1
        
        # BSSID, CLIENT, 00:
        if p.type == 1 and p.subtype == 10:
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1
        
        # BSSID, CLIENT, 00: or CLIENT, BSSID, 00: [re-check] (NOT IN BSSID?)
        if p.type == 1 and p.subtype == 11: 
            pass
            #print p.addr2, p.addr3	
            #CLIENT = p.addr2
            #BSSID = p.addr1
        
        # CLIENT, 00:, 00: 
        if p.type == 1 and p.subtype == 12: 
            #print p.addr2, p.addr3	
            CLIENT = p.addr1
            #BSSID = p.addr1
        
        # TYPE = 2
        
        # CLIENT, BSSID, CLIENT
        if p.type == 2 and p.subtype == 0:
            #print p.addr2, p.addr3
            CLIENT = p.addr1 # p.addr1?
            BSSID = p.addr2
            
        # CLIENT, BSSID
        if p.type == 2 and p.subtype == 4:
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr3
        
        # BSSID, CLIENT, BSSID
        if p.type == 2 and p.subtype == 8: 
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1
        
        # BSSID, CLIENT, BSSID
        if p.type == 2 and p.subtype == 12:
            #print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1
        
        if BSSID in EXCLUDE: BSSID = "" # CLEAN BSSID

        #注释print
        if BSSID not in INVENTORY and BSSID not in EXCLUDE and p.type == 0:
            INVENTORY[BSSID] = set()
            #print "added..." + str(BSSID)
            #print SSID
            if BSSID in aps:
                pass
                #print aps[BSSID]
            else:
                pass
                #print ">"+str(BSSID)+"??"
            #print
        
        #return
        
        if BSSID in INVENTORY and BSSID not in EXCLUDE and p.type in TYPE and p.subtype in SUBTYPE: 
            
            if CLIENT != BSSID and CLIENT not in EXCLUDE: INVENTORY[BSSID].add(CLIENT)
            #return
            #print
            #print "START..."
            
            check_delay_time = int(time.time()) - init_delay_time
            
            if LOG != "" and DELAY < check_delay_time:
                with open(LOG, 'w') as f:
                    f.write("")
            
            
            for i in INVENTORY:

                o_bssid = str(i)
                try: o_ssid = str(aps[i][0])
                except: o_ssid = ""
                try: o_channel = str(aps[i][1])
                except: o_channel = ""
                try: o_crypto = str("|".join(aps[i][2]))
                except: o_crypto = ""
                try: o_signal = str(aps[i][3])
                except: o_signal = ""
                o_client = str("|".join(INVENTORY[i]))
                try:o_min_signal=str(aps[i][4])
                except:o_min_signal=""
                try:o_max_signal=str(aps[i][5])
                except:o_max_signal=""
                OUT = o_bssid +","+ o_ssid +","+ o_channel +","+ o_crypto +","+ o_signal+","+ o_min_signal+","+ o_max_signal +","+ o_client
                #print OUT

                if LOG != "" and DELAY < check_delay_time:

                    with open(LOG, 'a') as f:
                        f.write(OUT + "\n")
            
            if DELAY < check_delay_time:
                init_delay_time = int(time.time())
                
        return
    except Exception as e:
        pass
        print "** Error: " + str(traceback.format_exc())
        print


# -------------------------
# SNIFFER
# -------------------------
def sniffmgm_check(p):
    global TYPE
    global SUBTYPE
    global LOG
    global DELAY
    global init_delay_time
    global f
    IP = []

    try:

        SIGNAL = -(256 - ord(p.notdecoded[-4:-3]))
        # p = pkt[Dot11Elt]
        cap = p.sprintf("{Dot11Beacon:%Dot11Beacon.cap%}"
                        "{Dot11ProbeResp:%Dot11ProbeResp.cap%}").split('+')

        BSSID = ""
        SSID, CHANNEL = None, None
        crypto = []
        pDot11Elt = None
        CLIENT = ""

        try:
            pDot11Elt = p[Dot11Elt]
        except:
            pass
        while isinstance(pDot11Elt, Dot11Elt):
            BSSID = p[Dot11].addr3

            if pDot11Elt.ID == 0:
                SSID = p.info
            elif pDot11Elt.ID == 3:
                CHANNEL = ord(pDot11Elt.info)
            elif pDot11Elt.ID == 48:
                crypto.append("WPA2")
            elif pDot11Elt.ID == 221 and pDot11Elt.info.startswith('\x00P\xf2\x01\x01\x00'):
                crypto.append("WPA")
            pDot11Elt = pDot11Elt.payload

        #新增加一个接入点
        if SSID != None and SSID != "" and BSSID not in aps and BSSID not in EXCLUDE:
            #print BSSID, SSID, CHANNEL, crypto, SIGNAL
            aps[BSSID] = [SSID, CHANNEL, crypto, SIGNAL, SIGNAL, SIGNAL]
        elif BSSID in aps:
            aps[BSSID][3] = SIGNAL

        IP.append(str(p.addr1))
        IP.append(str(p.addr2))
        IP.append(str(p.addr3))

        if p.subtype in SUBTYPE:  # DEBUG
            pass
            # print p.type, p.subtype, IP, desc[p.subtype], SSID, CHANNEL, SIGNAL
        # return

        # TYPE = 0

        # BSSID, CLIENT, BSSID
        if p.type == 0 and p.subtype == 0:  # Association Request
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1

        # CLIENT, BSSID, BSSID
        if p.type == 0 and p.subtype == 1:  # Association Response
            # print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr2

        # CLIENT, FF: # + SSID (sometimes)
        if p.type == 0 and p.subtype == 4:  # Probe Request
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            try:
                SSID = str(p.info)
            except:
                SSID = ""

        # CLIENT, BSSID, BSSID # + SSID
        if p.type == 0 and p.subtype == 5:  # Probe Response
            # print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr3
            try:
                SSID = str(p.info)
            except:
                SSID = ""

        # 00:, BSSID, BSSID # + SSID
        if p.type == 0 and p.subtype == 8:  # Beacon Frame
            # print p.addr2, p.addr3
            # CLIENT = p.addr2
            BSSID = p.addr2
            try:
                SSID = str(p.info)

                signal_check = True
                sc_check = True
                channel_check=True
                crypto_check=True
                if aps[BSSID][1]!=CHANNEL:
                    channel_check=False
                flag = check_ssid_bssid_in_whitelist(SSID, BSSID)

                #ssid在白名单，但是mac不在白名单
                if (flag == False):
                    update_fakeaplist(SSID, BSSID,False,signal_check,sc_check,channel_check)
                #ssid bssid都在白名单
                elif SSID in SSIDWhiteList and BSSID in MACWhiteList:
                    if channel_check==False:
                        update_fakeaplist(SSID, BSSID, True, signal_check, sc_check,channel_check)
                    signal_check=compare_signal_diff(SIGNAL,SSID,BSSID)
                    if (compare_sc_diff(p) == False):
                        sc_check = False

                    if sc_check == False:
                        update_fakeaplist(SSID, BSSID,True,signal_check,sc_check,channel_check)
                    # if sc_check==True and signal_check==False:
                    #     update_fakeaplist(SSID,BSSID,True,sc_check,signal_check)
            except:
                SSID = ""

        # BSSID, CLIENT, BSSID
        if p.type == 0 and p.subtype == 10:  # Disassociation
            #print 'disasso found'
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1

            destmac = p.addr1
            if destmac in disassociationAttackdic:
                disassociationAttackdic[destmac] += 1
            else:
                devdic[destmac] = 1
                disassociationAttackdic[destmac] = 1

        # CLIENT, BSSID, BSSID
        if p.type == 0 and p.subtype == 11:  # Authentication
            # print p.addr2, p.addr3
            CLIENT = p.addr1
            BSSID = p.addr2

            destmac = p.addr1
            global authAttackTimes
            authAttackTimes += 1;

            if destmac in authAttackdic:
                authAttackdic[destmac] += 1
            else:
                devdic[destmac] = 1
                authAttackdic[destmac] = 1

        # CLIENT, BSSID, BSSID
        if p.type == 0 and p.subtype == 12:  # Deauthentication
            destmac = p.addr1
            if destmac in deauthAttackdic:
                deauthAttackdic[destmac] += 1
            else:
                devdic[destmac] = 1
                deauthAttackdic[destmac] = 1

        # CLIENT, BSSID [re-check] (NOT IN BSSID?)
        if p.type == 0 and p.subtype == 13:  # Acknowledgement | Action frames
            pass
            # print p.addr2, p.addr3
            # CLIENT = p.addr2
            # BSSID = p.addr1

        # TYPE = 1

        # BSSID, CLIENT, 00:
        if p.type == 1 and p.subtype == 10:
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1

        # BSSID, CLIENT, 00: or CLIENT, BSSID, 00: [re-check] (NOT IN BSSID?)
        if p.type == 1 and p.subtype == 11:
            pass
            # print p.addr2, p.addr3
            # CLIENT = p.addr2
            # BSSID = p.addr1

        # CLIENT, 00:, 00:
        if p.type == 1 and p.subtype == 12:
            # print p.addr2, p.addr3
            CLIENT = p.addr1
            # BSSID = p.addr1

        # TYPE = 2

        # CLIENT, BSSID, CLIENT
        if p.type == 2 and p.subtype == 0:
            # print p.addr2, p.addr3
            CLIENT = p.addr1  # p.addr1?
            BSSID = p.addr2

        # CLIENT, BSSID
        if p.type == 2 and p.subtype == 4:
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr3

        # BSSID, CLIENT, BSSID
        if p.type == 2 and p.subtype == 8:
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1

        # BSSID, CLIENT, BSSID
        if p.type == 2 and p.subtype == 12:
            # print p.addr2, p.addr3
            CLIENT = p.addr2
            BSSID = p.addr1

        if BSSID in EXCLUDE: BSSID = ""  # CLEAN BSSID


        #注释print
        if BSSID not in INVENTORY and BSSID not in EXCLUDE and p.type == 0:
            INVENTORY[BSSID] = set()
            #print "added..." + str(BSSID)
            #print SSID
            if BSSID in aps:
                pass
                #print aps[BSSID]
            else:
                pass
                #print ">" + str(BSSID) + "??"
            #print

        # return

        if BSSID in INVENTORY and BSSID not in EXCLUDE and p.type in TYPE and p.subtype in SUBTYPE:

            if CLIENT != BSSID and CLIENT not in EXCLUDE: INVENTORY[BSSID].add(CLIENT)
            # return
            # print
            # print "START..."

            check_delay_time = int(time.time()) - init_delay_time

            if LOG != "" and DELAY < check_delay_time:
                with open(LOG, 'w') as f:
                    f.write("")

            for i in INVENTORY:

                o_bssid = str(i)
                try:
                    o_ssid = str(aps[i][0])
                except:
                    o_ssid = ""
                try:
                    o_channel = str(aps[i][1])
                except:
                    o_channel = ""
                try:
                    o_crypto = str("|".join(aps[i][2]))
                except:
                    o_crypto = ""
                try:
                    o_signal = str(aps[i][3])
                except:
                    o_signal = ""
                o_client = str("|".join(INVENTORY[i]))
                try:
                    o_min_signal = str(aps[i][4])
                except:
                    o_min_signal = ""
                try:
                    o_max_signal = str(aps[i][5])
                except:
                    o_max_signal = ""
                OUT = o_bssid + "," + o_ssid + "," + o_channel + "," + o_crypto + "," + o_signal + "," + o_min_signal + "," + o_max_signal + "," + o_client
                # print OUT

                if LOG != "" and DELAY < check_delay_time:
                    with open(LOG, 'a') as f:
                        f.write(OUT + "\n")

            if DELAY < check_delay_time:
                init_delay_time = int(time.time())

        return
    except Exception as e:
        pass
        print "** Error: " + str(traceback.format_exc())
        print

# Channel hopper - This code is very similar to that found in airoscapy.py (http://www.thesprawl.org/projects/airoscapy/)
#需要在该函数中指定频道
def channel_hopper(interface):
    global  CHANNEL
    global CHANNEL_SCAN_
    os.system("iwconfig %s channel %d" % (interface, CHANNEL_SCAN))
    # while True:
    #     try:
    #         #channel = random.randrange(1,13)
    #         channel = random.choice(CHANNEL)
    #         os.system("iwconfig %s channel %d" % (interface, channel))
    #         time.sleep(1)
    #     except KeyboardInterrupt:
    #         break

def stop_channel_hop(signal, frame):
    # set the stop_sniff variable to True to stop the sniffer
    global stop_sniff
    stop_sniff = True
    channel_hop.terminate()
    channel_hop.join()

try:
    init_time_out=60
    print 'Please wait '+str(init_time_out)+'s until the whitelist established successfully...'
    channel_hop = Process(target = channel_hopper, args=(INTERFACE,))
    channel_hop.start()
    signal.signal(signal.SIGINT, stop_channel_hop)
    sniff(iface=INTERFACE, prn=sniffmgmt_init,timeout=init_time_out)

    white_list=aps
    print 'the ap whitelist on channel '+str(CHANNEL_SCAN)+'is:'

    for bssid in white_list.keys():
        print str(bssid),aps[bssid]

    print 'The detector is running...'
    while(True):
        timeout=20
        devdic = {}
        deauthAttackdic = {}
        disassociationAttackdic = {}
        authAttackdic = {}
        authAttackTimes = 0
        last_sc={}
        fakeap_list={}
        fakeap_sc_time_list = {}
        fakeap_signal_time_list={}
        margin=timeout
        disass_dos_margin=6
    
        sniff(iface=INTERFACE, prn=sniffmgm_check, timeout=timeout)
        print 'sniff finished'
        for ssid in fakeap_list.keys():
            # print ssid
            # print fakeap_sc_time_list[ssid]
            # print fakeap_list[ssid]
            #sc错误次数和signal错误次数都不在允许范围内，才判断为假，报错是因为有可能一次都没错，出现key error
            if ssid in fakeap_sc_time_list.keys() and fakeap_sc_time_list[ssid]>margin and ssid in fakeap_signal_time_list.keys() and fakeap_signal_time_list[ssid]>margin:
                print '[+]Found fake ap！'
                print ssid,fakeap_list[ssid]

        print('current scan is done,the next will begin')
        print('--------------------------------------------------------------')

except Exception as e:
    print str(e)
    print "Bye ;)"